package com.beiding.utils;

import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.ImmediateAcknowledgeAmqpException;
import org.springframework.amqp.core.*;

public class AmqpUtils {

    /*

        超时矢量:

                起点-(等待时长)->终点

                将任务在起点进行触发,等待一段时间在终点处进行执行

     */


    private static String prefix;

    public static void setPrefix(String prefix) {

        if (AmqpUtils.prefix == null) {
            AmqpUtils.prefix = prefix+".";
        } else if (!AmqpUtils.prefix.equals(prefix + ".")) {
            //前缀只能指定一次,如果试图修改前缀则会报错
            throw new RuntimeException("不允许重复指定前缀");
        }

    }



    //用于异步操作的队列
    public static String asyncName(String topic) {
        return prefix.toString() + topic + ".async";
    }


    public static Queue async(String topic) {
        return createQueue(asyncName(topic));
    }

    //用于生成超时矢量的名称
    public static String vectorStartName(String topic) {
        return prefix.toString() + topic + ".vector.start";
    }

    public static String vectorEndName(String topic) {
        return prefix.toString() + topic + ".vector.end";
    }


    //创建一个超时矢量的终点
    public static Queue vectorEnd(String topic) {
        return createQueue(vectorEndName(topic));
    }


    //创建一个超时矢量的起点
    public static Queue vectorStart(String topic, long waitingSeconds) {

        //将矢量绑定到终点
        return createQueue(vectorStartName(topic), waitingSeconds, vectorEndName(topic));
    }


    //创建一个超时矢量的起点
    public static Queue vectorStart(String topic) {

        //将矢量绑定到终点
        return createQueue(vectorStartName(topic), vectorEndName(topic));
    }


    //创建一个队列,指定其死信交换机,以及死信路由键
    public static Queue createQueue(String name, String deadMessageExchange, String deadMessageRoutingKey) {
        return QueueBuilder.durable(name)
                .withArgument("x-dead-letter-exchange", deadMessageExchange) //死信交换机
                .withArgument("x-dead-letter-routing-key", deadMessageRoutingKey) //路由键
                .build();
    }

    //创建一个队列,指定死亡时处理私网消息的队列
    public static Queue createQueue(String name, String deadMessageQueue) {
        return createQueue(name, "", deadMessageQueue); //  使用rabbitmq中的默认交换机""
    }

    //创建一个队列,并制定多长消息存活时长,以及死亡时处理的队列
    public static Queue createQueue(String name, long messageTtlSeconds, String deadMessageQueue) {
        return createQueue(name, deadMessageQueue, messageTtlSeconds, "");
    }

    //创建一个队列,并指定其消息存活时间
    public static Queue createQueue(String name, long messageTtlSeconds) {
        return QueueBuilder.durable(name)
                .withArgument("x-message-ttl", 1000 * messageTtlSeconds).build();
    }


    //简单创建一个队列
    public static Queue createQueue(String name) {
        return QueueBuilder.durable(name).build();
    }

    //创建一个队列,指定死信交换机,死信路由键,以及存活时间
    public static Queue createQueue(String name, String deadMessageRoutingKey, long messageTtlSeconds, String deadMessageExchange) {
        return QueueBuilder.durable(name)
                .withArgument("x-message-ttl", 1000 * messageTtlSeconds)  //超时时间
                .withArgument("x-dead-letter-exchange", deadMessageExchange) //死信交换机
                .withArgument("x-dead-letter-routing-key", deadMessageRoutingKey) //路由键
                .build();
    }


    //队列绑定值交换机
    public static Binding queueBindToExchange(Queue queue, String routingKey, TopicExchange toExchange) {
        return BindingBuilder.bind(queue).to(toExchange).with(routingKey);
    }

    public static Binding queueBindToExchange(Queue queue, String routingKey, DirectExchange toExchange) {
        return BindingBuilder.bind(queue).to(toExchange).with(routingKey);
    }

    public static Binding queueBindToExchange(Queue queue, FanoutExchange toExchange) {
        return BindingBuilder.bind(queue).to(toExchange);
    }


    //交给异常队列进行处理
    public static void error(Throwable e) {
        throw new AmqpRejectAndDontRequeueException("交由异常队列处理");
    }

    //异常被忽略
    public static void pass(Throwable e) {
        throw new ImmediateAcknowledgeAmqpException("通过");
    }


}
